"""
管理后台-组织机构服务
"""

from datetime import datetime
from typing import List, Optional, Set, Dict, Any

from tortoise.expressions import Q
from tortoise.transactions import atomic

from app.core.constants import BoolEnum, OrgTypeEnum
from app.core.exceptions import APIException
from app.core.i18n import t
from app.models.user_model import OrganizationModel
from app.schemas.admin.admin_organization_schemas import (
    AdminOrganizationCreateRequest,
    AdminOrganizationListFilters,
    AdminOrganizationListResponse,
    AdminOrganizationResponse,
    AdminOrganizationTreeNode,
    AdminOrganizationTreeResponse,
    AdminOrganizationUpdateRequest,
)
from app.schemas.common import CurrentUser, OrderSchema, PaginationParams
from app.services.base import filter_query
from app.utils.tree_helper import TreeHelper


class AdminOrganizationService:
    """管理后台-组织机构服务"""

    @staticmethod
    async def _validate_parent(parent_id: Optional[int], org_id: Optional[int] = None) -> Optional[OrganizationModel]:
        """验证父级组织"""
        if not parent_id:
            return None

        # 检查父级是否存在
        parent = await OrganizationModel.get_or_none(id=parent_id)
        if not parent:
            raise APIException(message=t("error.organization.parent_not_found"))

        # 检查父级状态
        if parent.is_show == BoolEnum.FALSE:
            raise APIException(message=t("error.organization.parent_disabled"))

        # 如果是更新操作，检查是否选择自己或子级作为父级
        if org_id:
            if parent_id == org_id:
                raise APIException(message=t("error.organization.cannot_set_self_as_parent"))

            # 获取所有子级ID
            children_ids = await AdminOrganizationService._get_children_ids(org_id)
            if parent_id in children_ids:
                raise APIException(message=t("error.organization.cannot_set_child_as_parent"))

        return parent

    @staticmethod
    async def _validate_name_unique(name: str, parent_id: Optional[int], org_id: Optional[int] = None) -> None:
        """验证名称在同级下唯一"""
        query = OrganizationModel.filter(name=name, parent_id=parent_id)
        if org_id:
            query = query.exclude(id=org_id)

        if await query.exists():
            raise APIException(message=t("error.organization.name_exists"))

    @staticmethod
    async def _validate_max_depth(parent_id: Optional[int], org_type: OrgTypeEnum) -> None:
        """验证最大层级深度"""
        if not parent_id:
            return

        # 计算当前层级深度
        depth = 1
        current = await OrganizationModel.get(id=parent_id)
        while current.parent_id:
            depth += 1
            current = await current.parent

        # 根据组织类型判断最大层级
        max_depth = {
            OrgTypeEnum.COMPANY: 5,  # 公司最多5层
            OrgTypeEnum.DEPARTMENT: 3,  # 部门最多3层
        }.get(org_type, 5)

        if depth >= max_depth:
            raise APIException(message=t("error.organization.max_depth_exceeded"))

    @staticmethod
    async def _get_children_ids(org_id: int) -> Set[int]:
        """获取所有子级ID(包括孙级)"""
        # 获取所有组织数据
        orgs = await OrganizationModel.all()

        # 转换为树形结构所需的字典列表
        org_list = []
        for org in orgs:
            org_dict = {"id": org.id, "parent_id": org.parent_id}
            org_list.append(org_dict)

        # 使用TreeHelper构建树
        root = TreeHelper.list_to_tree(org_list)

        # 查找目标节点
        target = TreeHelper.find_node(root, lambda x: x.val["id"] == org_id)
        if not target:
            return set()

        # 获取所有子节点ID
        children_ids = set()

        def collect_children(node):
            for child in node.children:
                children_ids.add(child.val["id"])
                collect_children(child)

        collect_children(target)
        return children_ids

    @classmethod
    @atomic()
    async def create(cls, data: AdminOrganizationCreateRequest, current_user: CurrentUser) -> AdminOrganizationResponse:
        """创建组织"""
        # 1. 验证父级
        parent = await cls._validate_parent(data.parent_id)

        # 2. 验证名称唯一
        await cls._validate_name_unique(data.name, data.parent_id)

        # 3. 验证层级深度
        await cls._validate_max_depth(data.parent_id, data.org_type)

        # 4. 创建组织
        org = await OrganizationModel.create(**data.model_dump(), created_by=current_user.id)

        return AdminOrganizationResponse.model_validate(org)

    @classmethod
    @atomic()
    async def update(
        cls,
        org_id: int,
        data: AdminOrganizationUpdateRequest,
        current_user: CurrentUser,
    ) -> AdminOrganizationResponse:
        """更新组织"""
        # 1. 检查组织是否存在
        org = await OrganizationModel.get_or_none(id=org_id)
        if not org:
            raise APIException(message=t("error.organization.not_found"))

        # 2. 如果更新父级，进行验证
        if data.parent_id is not None:
            await cls._validate_parent(data.parent_id, org_id)

        # 3. 如果更新名称，验证唯一性
        if data.name is not None:
            await cls._validate_name_unique(data.name, data.parent_id or org.parent_id, org_id)

        # 4. 如果更新类型，验证层级
        if data.org_type is not None:
            await cls._validate_max_depth(data.parent_id or org.parent_id, data.org_type)

        # 5. 更新数据
        update_data = data.model_dump(exclude_unset=True)
        await org.update(**update_data)

        return AdminOrganizationResponse.model_validate(org)

    @classmethod
    @atomic()
    async def delete(cls, org_id: int, current_user: CurrentUser) -> None:
        """删除组织"""
        # 1. 检查组织是否存在
        org = await OrganizationModel.get_or_none(id=org_id)
        if not org:
            raise APIException(message=t("error.organization.not_found"))

        # 2. 检查是否有子级
        if await OrganizationModel.filter(parent_id=org_id).exists():
            raise APIException(message=t("error.organization.has_children"))

        # 3. 检查是否有关联用户
        if await org.users.all().count() > 0:
            raise APIException(message=t("error.organization.has_users"))

        # 4. 执行删除(软删除)
        await org.delete()

    @classmethod
    async def get_detail(cls, org_id: int) -> AdminOrganizationResponse:
        """获取组织详情"""
        # 1. 获取组织
        org = await OrganizationModel.get_or_none(id=org_id)
        if not org:
            raise APIException(message=t("error.organization.not_found"))

        return AdminOrganizationResponse.model_validate(org)

    @classmethod
    async def get_list(
        cls,
        filters: AdminOrganizationListFilters,
        order: OrderSchema,
        pagination: PaginationParams,
    ) -> AdminOrganizationListResponse:
        """获取组织列表"""
        # 1. 构建查询
        query = OrganizationModel.all()

        special_conditions = {
            "name": "name__icontains",
        }
        query = await filter_query(query, filters, special_conditions)

        # 3. 应用排序
        if order.order_by:
            query = query.order_by(*order.get_tortoise_orders())

        # 4. 获取总数
        total = await query.count()

        # 5. 应用分页
        items = await query.offset(pagination.get_skip()).limit(pagination.page_size).all()

        # 6. 构建响应
        return AdminOrganizationListResponse(
            total=total,
            items=[AdminOrganizationResponse.model_validate(item) for item in items],
        )

    @classmethod
    async def get_tree(cls) -> AdminOrganizationTreeResponse:
        """获取组织树"""
        # 1. 获取所有组织
        orgs = await OrganizationModel.all().order_by("sort")

        # 2. 转换为树形结构所需的字典列表
        org_list = []
        for org in orgs:
            org_dict = {
                "id": org.id,
                "name": org.name,
                "parent_id": org.parent_id,
                "sort": org.sort,
                "org_type": org.org_type,
                "is_show": org.is_show,
            }
            org_list.append(org_dict)

        # 3. 使用TreeHelper构建树
        root = TreeHelper.list_to_tree(org_list)
        if not root:
            return []

        # 4. 转换为响应模型
        def convert_to_tree_node(node) -> AdminOrganizationTreeNode:
            return AdminOrganizationTreeNode(
                id=node.val["id"],
                name=node.val["name"],
                parent_id=node.val["parent_id"],
                sort=node.val["sort"],
                org_type=node.val["org_type"],
                is_show=node.val["is_show"],
                children=[convert_to_tree_node(child) for child in node.children],
            )

        # 5. 返回根节点列表
        return [convert_to_tree_node(node) for node in root.children]
